package lib.bone.admin.controller.flow;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lib.bone.admin.anno.FormLock;
import lib.bone.admin.anno.WebLog;
import lib.bone.admin.constant.MethodTypeConst;
import lib.bone.admin.controller.system.SysUserController;
import lib.bone.admin.domain.vo.FlowTaskVO;
import lib.bone.audit.workload.domain.NepuWorkload;
import lib.bone.flow.dao.FlowTaskDAO;
import lib.bone.flow.domain.dto.FlowTaskDTO;
import lib.bone.flow.domain.dto.FlowTaskQueryByDTO;
import lib.bone.flow.domain.dto.FlowTaskQueryDTO;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.common.core.redis.RedisCache;
import lib.bone.flow.constant.FlowTaskHandleConst;
import lib.bone.flow.constant.FlowTaskStatusConst;
import lib.bone.flow.domain.entity.FlowAttach;
import lib.bone.flow.domain.entity.FlowTask;
import lib.bone.flow.domain.vo.AnalysisVO;
import lib.bone.flow.service.FlowAttachService;
import lib.bone.flow.service.FlowTaskService;
import lib.bone.flow.service.FlowWorkCtl;
import lib.bone.flow.service.FlowWorkService;
import lib.bone.system.domain.entity.SysUser;
import lib.bone.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author: kindear
 */
@Slf4j
@RestController
@RequestMapping("flow")
@Api(tags = "流程任务")
public class FlowTaskCustomController {

    @Autowired
    FlowWorkService flowWorkService;

    @Autowired
    FlowTaskService flowTaskService;

    @Autowired
    FlowAttachService flowAttachService;



    @Autowired
    SysUserService userService;

    @Autowired
    SysUserController userCtl;

    @Autowired
    FlowWorkCtl flowWorkCtl;

    @Autowired
    RedisCache redisCache;

    @Autowired
    FlowTaskDAO flowTaskDAO;


    @GetMapping("getww")
    @ApiOperation(value = "去重查询")
    public ResponseDTO searchww(){
        FlowTask flowTask1 = new FlowTask();
        flowTask1.setTaskStatus("REJECT");
        Example example = Example.of(flowTask1);
        List<FlowTask> list = flowTaskDAO.findAll(example);
        System.out.println(list.size());
        Map<String,String> map = new HashMap<>();
        Map<String,String> map1 = new HashMap<>();
        for (FlowTask flowTask : list) {
            map.put(flowTask.getServiceId(),flowTask.getServiceName());
        }

        for (FlowTask flowTask : list) {
            map1.put(flowTask.getServiceName(),flowTask.getServiceId());
        }

        System.out.println("map1.size():"+map1.size());

        return ResponseDTO.succData(map.size());


    }


    @GetMapping("get")
    @ApiOperation(value = "查询")
    public ResponseDTO search(FlowTaskQueryByDTO dto){

        Sort sort;
        if(dto.getOrder().equalsIgnoreCase("DESC")){
            sort = Sort.by(Sort.Direction.DESC, dto.getSortBy());
        }else {
            sort = Sort.by(Sort.Direction.ASC, dto.getSortBy());
        }
        // tips : 页码对应 - 1
        Pageable pageable = PageRequest.of(dto.getPageNum() - 1 , dto.getPageSize(), sort);
        FlowTask workload = new FlowTask();
        BeanUtil.copyProperties(dto,workload, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        ExampleMatcher matcher = ExampleMatcher.matching();
        matcher = matcher.withMatcher("serviceName",ExampleMatcher.GenericPropertyMatchers.contains());
        Example<FlowTask> example = Example.of(workload,matcher);
        return ResponseDTO.succData(flowTaskService.searchList(pageable,example));
    }

    @GetMapping("tasks")
    @ApiOperation(value = "查询全部流程任务")
    public ResponseDTO getList(FlowTaskQueryDTO dto){
        Sort sort;
        if(dto.getOrder().equalsIgnoreCase("DESC")){
            sort = Sort.by(Sort.Direction.DESC, dto.getSortBy());
        }else {
            sort = Sort.by(Sort.Direction.ASC, dto.getSortBy());
        }

        // tips : 页码对应 - 1
        Pageable pageable = PageRequest.of(dto.getPageNum() - 1 , dto.getPageSize(), sort);

        FlowTask task = new FlowTask();
        BeanUtil.copyProperties(dto,task, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Example<FlowTask> example = Example.of(task);

//        flowWorkController.flowWorkTaskCreate(flowWorkId);


        return flowTaskService.getList(pageable,example);
    }



    @WebLog(module = "bone-flow",operate = MethodTypeConst.UPDATE)
    @PostMapping("tasks/{taskId}/reject")
    @FormLock(lockKey = "FLOW_REJECT",lockSeconds = 3,needLogin = true)
    @ApiOperation(value = "驳回流程任务")
    public ResponseDTO rejectTask(@PathVariable("taskId") String taskId,@RequestParam("message") String message){
        // 获取当前token 对应用户
        String operator = StpUtil.getLoginIdAsString();
        Boolean isLocked = redisCache.getCacheObject("LOCK-FLOW-ACT:"+operator);
        if (Validator.isNotEmpty(isLocked)){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"禁止重复请求!");
        }else {
            redisCache.setCacheObject("LOCK-FLOW-ACT:"+operator, true, 3, TimeUnit.SECONDS);
        }
        //查询用户信息
        Optional<SysUser> userOp = userService.getById(StpUtil.getLoginIdAsLong());
        if (!userOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.UNAUTHORIZED);
        }
        SysUser user = userOp.get();
        /**
         * 查询TASK 信息
         */
        Optional<FlowTask> taskOp = flowTaskService.getById(taskId);
        if (!taskOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        FlowTask task = taskOp.get();
        /**
         * 设置信息 --  写入
         */
        FlowAttach attach = new FlowAttach();
        attach.setAttach(message);
        attach.setActUserId(operator);
        attach.setActUserName(user.getNickName());
        attach.setFlowWorkId(task.getFlowWorkId());
        attach.setFlowNodeId(task.getFlowNodeId());
        attach.setFlowNodeName(task.getTaskName());
        attach.setFlowTaskHandle(FlowTaskHandleConst.REJECT);
        if (Validator.isEmpty(message)){
            log.warn("流程[{}]操作[{}]流转空信息",task.getFlowWorkId(),FlowTaskHandleConst.REJECT);
        }
        // 非空写入信息
        flowAttachService.saveOne(attach);
        return flowWorkCtl.rejectTask(taskId,operator,null);
    }

    @WebLog(module = "bone-flow",operate = MethodTypeConst.UPDATE)
    @PostMapping("tasks/{taskId}/complete")
    @FormLock(lockKey = "FLOW_COMPLETE",lockSeconds = 3,needLogin = true)
    @ApiOperation(value = "完成流程任务")
    public ResponseDTO completeTask(@PathVariable("taskId") String taskId,@RequestParam("message") String message){
        log.info("流程TASK:{}",taskId);
        // 获取当前token 对应用户
        String operator = StpUtil.getLoginIdAsString();
        //查询用户信息
        Optional<SysUser> userOp = userService.getById(StpUtil.getLoginIdAsLong());
        if (!userOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.UNAUTHORIZED);
        }
        SysUser user = userOp.get();
        /**
         * 查询TASK 信息
         */
        Optional<FlowTask> taskOp = flowTaskService.getById(taskId);
        if (!taskOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        FlowTask task = taskOp.get();
        FlowAttach attach = new FlowAttach();
        attach.setAttach(message);
        attach.setActUserId(operator);
        attach.setActUserName(user.getNickName());
        attach.setFlowWorkId(task.getFlowWorkId());
        attach.setFlowNodeId(task.getFlowNodeId());
        attach.setFlowNodeName(task.getTaskName());
        attach.setFlowTaskHandle(FlowTaskHandleConst.COMPLETE);
        // 非空写入信息
        if (Validator.isEmpty(message)){
            log.warn("流程[{}]操作[{}]流转空信息",task.getFlowWorkId(),FlowTaskHandleConst.COMPLETE);
        }
        flowAttachService.saveOne(attach);

        //完成流程任务
        return flowWorkCtl.completeTask(taskId,operator,null);
    }


    /**
     * 查询单个流程
     */
    @GetMapping("tasks/{taskId}")
    @ApiOperation(value = "查询流程任务信息")
    public ResponseDTO<FlowTask> getTask(@PathVariable("taskId") String taskId){
        Optional<FlowTask> taskOp = flowTaskService.getById(taskId);
        if (!taskOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }

        return ResponseDTO.succData(taskOp.get());
    }

    /**
     * 查询单个流程补充版本
     */
    @Transactional
    @GetMapping("tasks/{taskId}/lazy")
    @ApiOperation(value = "查询流程任务信息(LAZY)")
    public ResponseDTO<FlowTaskVO> getTaskLazy(@PathVariable("taskId") String taskId){
        Optional<FlowTask> taskOp = flowTaskService.getById(taskId);
        if (!taskOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        FlowTask task = taskOp.get();
        FlowTaskVO taskVO = new FlowTaskVO();
        BeanUtil.copyProperties(task,taskVO,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        taskVO.setInitiator(userCtl.getUserBasic(Long.parseLong(task.getInitiator())).getData());
        taskVO.setActUser(userCtl.getUserBasic(Long.parseLong(task.getActUserId())).getData());
        taskVO.setOperator(userCtl.getUserBasic(Long.parseLong(task.getOperator())).getData());
        return ResponseDTO.succData(taskVO);
    }

    /**
     * 获取流程操作统计信息
     */
    @GetMapping("tasks/analysis")
    @ApiOperation(value = "分析流程任务信息")
    public ResponseDTO<AnalysisVO> analysisTask(@RequestParam(value = "userId",required = false) String userId){
        if (Validator.isEmpty(userId)){
            userId = StpUtil.getLoginIdAsString();
        }
        Long completedCount = flowTaskService.countTaskStatus(FlowTaskStatusConst.FINISHED,userId);
        Long rejectedCount = flowTaskService.countTaskStatus(FlowTaskStatusConst.REJECT,userId);
        Long processCount = flowTaskService.countTaskStatus(FlowTaskStatusConst.CREATED,userId);
        AnalysisVO res = new AnalysisVO();
        res.setCompletedCount(completedCount);
        res.setRejectedCount(rejectedCount);
        res.setProcessCount(processCount);
        return ResponseDTO.succData(res);
    }

}
